﻿/*
Description : 为js提供类机制，并拥有继承，多态，重用等特性
Author      : 侯锋
Email       : admin@xhou.net
*/

$helper = {
    trim: function (str) {
        if (str && str.trim)
            return str.trim();
        else
            return str.replace(/(^[\\s]*)|([\\s]*$)/g, "");
    },
    isNull: function (obj) {
        return obj == null;
    },
    isFunction: function (obj) {
        return typeof obj === "function";
    },
    isString: function (obj) {
        return typeof obj === 'string';
    },
    isNumber: function (obj) {
        return typeof obj === 'number';
    },
    isElement: function (obj) {
        if (window.Element)
            return obj instanceof Element;
        else
            return obj.tagName && obj.nodeType && obj.nodeName && obj.attributes && obj.ownerDocument;
    },
    isText: function (obj) {
        return obj instanceof Text;
    },
    isObject: function (obj) {
        return typeof obj === "object";
    },
    isArray: function (obj) {
        if (!obj)
            return false;
        var _isArray = ((obj instanceof Array)
                        || (!this.isString(obj) && obj.length && this.isNumber(obj.length)));
        return _isArray;
    },
    each: function (obj, fn) {
        if (this.isArray(obj)) {
            for (var i = 0; i < obj.length; i++)
                fn.call(obj[i], i);
        }
        else {
            for (var i in obj)
                if ($helper.isFunction(fn))
                    fn.call(obj[i], i);
        }
        return obj;
    }
};

/*class“关键字”实现*/
function $class(params) {
    /// <summary>
    /// 定义类型
    /// </summary>
    /// <param name="params">类型主体</param>
    /// <returns type="">类型</returns>
    //定义新类型
    var newClass = function () {
        /// <summary>类型</summary>
        var me = this;
        //#region 改变父类的作用域，判断父类类型的向个系统函数不能改变作用域
        if (me.$base) {
            for (var name in me.$base) {
                if (name != "$is" && name != "$base" && name != "$type"
                    && name != "$baseType" && $helper.isFunction(me.$base[name])) {
                    var func = me.$base[name];
                    me.$base[name] = function () {
                        func.apply(me, arguments);
                    }
                }
            }
        }
        //#endregion 
        me.$type = newClass;
        me.$is = function (t) {
            return me.$type === t || me.$baseType === t
            || (me.$base != null && me.$base.$is != null && me.$base.$is(t));
        }
        //调用构造
        var rs = null;
        if (me.$init && $helper.isFunction(me.$init))
            rs = me.$init.apply(me, arguments);
        //调用扩展构造
        if (me.$initList) {
            for (var i in me.$initList)
                if (me.$initList[i] && $helper.isFunction(me.$initList[i]))
                    me.$initList[i].apply(me, arguments);
        }
        //返回
        return rs;
    };
    //添加扩展方法
    var _extend = function (fns, internal) {//私有
        if (!newClass.prototype.$initList)
            newClass.prototype.$initList = [];
        for (var name in fns) {
            if (!internal && name == "$init" && $helper.isFunction(fns[name]))
                newClass.prototype.$initList.push(fns[name]);
            else
                newClass.prototype[name] = fns[name];
        }
        return newClass;
    };
    newClass.$extend = function (fns) {
        _extend(fns, false);
    };
    newClass.$static = function (fns) {
        for (var name in fns) {
            newClass[name] = fns[name];
            if (name == "$init" && $helper.isFunction(fns[name]))
                newClass[name].apply(newClass);
        }
        return newClass;
    };
    //#region 将成员附加到当前类中
    if ($helper.isFunction(params)) {
        var _body = new params();
        params = _body;
    }
    if (params.$base) {
        var base = params.$base;
        params.$baseType = base;
        params.$base = new base();
        //添加
        _extend(params.$base, true); //添加父类成员
        _extend(params, true); //添加当前类成员
        newClass.$static(params.$baseType); //添加静态成员
    }
    else {
        _extend(params, true);
    }
    //#endregion
    //返回新类类
    return newClass;
};

/*event “关键字”实现，需配和类或对象才能使用*/
function $event(src, name, bindType) {
    /// <summary>
    /// 创建一个事件
    /// </summary>
    /// <param name="src">事件源对象</param>
    /// <param name="name">事件名</param>
    /// <param name="bindType">绑定类型</param>
    /// <returns type="">事件</returns>
    //默认为当前对象，如果没有在一个自定义对象中使用，this指向的是window
    var me = this;
    //默契第一个参数据事件名，第二个为对象
    if (src && $helper.isString(name))
        me = src;
    //为了支持第一个参数为对象，第二个参为事件名的写法
    if (name && $helper.isString(src)) {
        me = name;
        name = src;
    }
    //事件存放列表
    if (!me._eventList) me._eventList = {};
    //如果事件不存则添加
    if (!me._eventList[name]) {
        me._eventList[name] = [];
        //用以支持系统对象的系统事件
        me.addEventListener = me.addEventListener || function (name, fn) {
            if (me.attachEvent)
                me.attachEvent("on" + name, fn);
        };
        me.removeEventListener = me.removeEventListener || function (name, fn) {
            if (me.detachEvent)
                me.detachEvent("on" + name, fn);
        };
        //处理绑定类型
        if (bindType == null && bindType != 0) {
            if ($helper.isArray(me) && !$helper.isElement(me)) bindType = $event.bindType.child;
            else bindType = $event.bindType.self;
        }
        //实现对数组批量支持(支持数组及伪数组),迭代器
        me._each = function (fn, _bindType) {
            if ($helper.isArray(me) && !$helper.isElement(me)
            && $event.bindType.self != _bindType
            && me[0]) {
                $helper.each(me, fn);
            }
            return me;
        }
        //创建事件相关方法
        if (me[name]) me["$" + name] = me[name];
        me[name] = function (fn, obj) {
            /// <summary>事件</summary>
            if (fn && $helper.isFunction(fn))
                me[name].bind(fn, obj);
            else
                me[name].tigger.apply(me[name], arguments);
            return me;
        };
        me[name].clear = function () {
            /// <summary>清除</summary>
            //如果是数组或伪数组
            me._each(function () {
                $event(name, this).clear();
            }, bindType);
            //
            me._eventList[name] = [];
            return me;
        };
        me[name].has = function (fn) {
            var list = me._eventList[name];
            for (var i = 0; i < list.length; i++) {
                if (list[i] == fn)
                    return true;
            }
        };
        me[name].add = me[name].bind = function (fn, obj) {
            /// <summary>绑定</summary>
            //如果是数组或伪数组
            me._each(function () {
                $event(name, this).add(fn, obj);
            }, bindType);
            //
            if (me[name].has(fn) || $event.bindType.child == bindType)
                return me;
            fn._src = obj;
            me._eventList[name].push(fn);
            //如果为系统对象支持系统事件
            if (me.addEventListener && me.removeEventListener) {
                fn.$invoke = function (event) {
                    var rs = fn.apply(me, arguments);
                    if (rs === false) {//阻止事件冒泡
                        if (event.cancelBubble)
                            event.cancelBubble = true;
                        if (event.preventDefault)
                            event.preventDefault();
                        if (event.stopPropagation)
                            event.stopPropagation();
                    }
                }
                me.addEventListener(name, fn.$invoke);
            }
            return me;
        };
        me[name].remove = me[name].unbind = function (fn) {
            /// <summary>移除</summary>
            //如果是数组或伪数组
            me._each(function () {
                $event(name, this).remove(fn);
            }, bindType);
            //
            if ($event.bindType.child == bindType)
                return me;
            //
            if (me.addEventListener && me.removeEventListener) {
                me.removeEventListener(name, fn.$invoke);
            }
            //
            for (var i in me._eventList[name]) {
                if (me._eventList[name][i] = fn)
                    me._eventList[name][i] = null;
            }
            return me;
        };
        me[name].tigger = me[name].fire = function () {
            /// <summary>触发</summary>
            var args = arguments;
            //如果是数组或伪数组
            me._each(function () {
                $event(name, this).tigger.apply(child[name], args);
            }, bindType);
            //  
            if (me["$" + name]) {
                me["$" + name].apply(me, args);
                return;
            }
            //
            for (var i in me._eventList[name]) {
                if (me._eventList[name][i] != null) {
                    var src = me._eventList[name][i]._src;
                    if (src == null) src = me;
                    if (src)
                        me._eventList[name][i].apply(src, args);
                }
            }
            return me;
        };
    }
    //返回事件
    return me[name];
};

/*事件绑定类型*/
$event.bindType = {
    self: 0,
    child: 1,
    all: 2
};